iT邦幫忙

2025 iThome 鐵人賽

DAY 18
0
Mobile Development

從零開始學習 iOS系列 第 18

從零開始學習 iOS Day17 - MVVM架構

  • 分享至 

  • xImage
  •  

今天開始我們要來介紹App 常用功能,首先會從專案架構講起。

提到專案架構就不得不提到MVVM,所以今天我們會針對MVVM進行介紹。

什麼是MVVM

MVVM 是一種常見的專案架構模式,主要目的是 分離畫面 (UI) 與邏輯 (Logic),降低耦合、方便測試,讓程式更乾淨、可維護。

MVVM 分成三層:

  • Model → 資料來源 (例如使用者資料)
  • View → 負責顯示 UI (SwiftUI 的畫面)
  • ViewModel → 負責處理邏輯,把資料轉換後提供給 View

好處:

  • 降低耦合:View 與 Model 之間不直接互動
  • 方便測試:ViewModel 可以獨立測試,不需要 UI
  • 程式更乾淨:職責分明,維護更容易

ViewModel如何傳遞資料給View

MVVM 架構 中,ViewModel 的責任就是 管理狀態通知 View 更新

而在 SwiftUI 中,最常見的方式是搭配 Combine 框架:

  1. 在 ViewModel 中使用 @Published 發布狀態變更
  2. 在 View 中使用 @StateObject@ObservedObject 來接收資料更新
  3. 當資料變更時,SwiftUI 會自動更新畫面

範例:計數器

import SwiftUI
import Combine

class CounterViewModel: ObservableObject {
    // 使用 @Published 讓數值改變時能發出通知
    @Published var count = 0

    func increment() {
        count += 1
    }
}

struct CounterView: View {
    // 使用 @StateObject 讓 View 訂閱 ViewModel 的資料流
    @StateObject var viewModel = CounterViewModel()

    var body: some View {
        VStack {
            Text("目前數字:\(viewModel.count)")
                .font(.largeTitle)
            Button("加一") {
                viewModel.increment()
            }
        }
    }
}

https://github.com/jian-fu-hung/ithelp-2025/blob/main/image/Day17/%E6%88%AA%E5%9C%96%202025-10-02%20%E5%87%8C%E6%99%A81.52.10.png?raw=true

運作流程

  1. @Published var count 是一個 Publisher
  2. increment() 改變數值時,count 會透過 Combine 發出 新的值
  3. @StateObject 自動訂閱這個 Publisher,讓 View 收到新值並重新渲染。

範例實作:簡易登入

ViewModel

import SwiftUI
import Combine

class LoginViewModel: ObservableObject {
    // 使用者輸入
    @Published var username: String = ""
    @Published var password: String = ""
        
    // 狀態
    @Published var loginMessage: String = ""
        
        
    func login() {
        if username == "admin" && password == "1234" {
            loginMessage = "登入成功"
        } else {
            loginMessage = "帳號或密碼錯誤"
        }
    }
}

View

struct LoginView: View {
    @StateObject private var viewModel = LoginViewModel()
    
    var body: some View {
        VStack(spacing: 20) {
            TextField("帳號", text: $viewModel.username)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .padding(.horizontal)
            
            SecureField("密碼", text: $viewModel.password)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .padding(.horizontal)
            
            Button("登入") {
                viewModel.login()
            }
            .padding()
            
            Text(viewModel.loginMessage)
                .foregroundColor(.blue)
        }
        .padding()
    }
}

https://github.com/jian-fu-hung/ithelp-2025/blob/main/image/Day17/%E6%88%AA%E5%9C%96%202025-10-02%20%E5%87%8C%E6%99%A81.52.31.png?raw=true

登入成功

https://github.com/jian-fu-hung/ithelp-2025/blob/main/image/Day17/%E6%88%AA%E5%9C%96%202025-10-02%20%E5%87%8C%E6%99%A81.52.46.png?raw=true

登入失敗

https://github.com/jian-fu-hung/ithelp-2025/blob/main/image/Day17/%E6%88%AA%E5%9C%96%202025-10-02%20%E5%87%8C%E6%99%A81.52.55.png?raw=true

運作流程

  1. 使用者輸入帳號/密碼 → @Published username@Published password 發出更新。
  2. 按下「登入」時,ViewModel 執行邏輯並更新 loginMessage,畫面立即反映結果。

在這個範例中:

  • ViewModelLoginViewModel,負責處理登入邏輯
  • ViewLoginView,負責顯示 UI 並觸發事件

今日小結

  • MVVM 是一種架構模式,將程式分成 Model / View / ViewModel
  • SwiftUI 中透過 Combine (@Published@StateObject@ObservedObject) 來建立資料流
  • 好處是 降低耦合、方便測試、程式更乾淨
  • 我們用一個 登入功能 說明了 MVVM 的基本應用

明天預計會介紹第三方套件,讓開發更快速、更彈性。


上一篇
從零開始學習 iOS Day16 - Canvas
下一篇
從零開始學習 iOS Day18 - 第三方套件
系列文
從零開始學習 iOS24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言